package com.ddwl.user.service;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.ddwl.common.constant.*;
import com.ddwl.common.exception.ParamException;
import com.ddwl.common.feign.api.FundsApi;
import com.ddwl.common.feign.api.GateApi;
import com.ddwl.common.feign.api.ShopApi;
import com.ddwl.common.feign.api.WalletApi;
import com.ddwl.common.util.BeanConverUtils;
import com.ddwl.common.util.MySqlUtil;
import com.ddwl.schema.bo.base.PageBo;
import com.ddwl.schema.bo.funds.FundsPaymentBo;
import com.ddwl.schema.bo.funds.PayOrderCreBo;
import com.ddwl.schema.bo.user.AgentOrderBo;
import com.ddwl.schema.bo.user.AgentPayOrderBo;
import com.ddwl.schema.bo.user.AgentSendBo;
import com.ddwl.schema.bo.user.UpgradeAgentPageBo;
import com.ddwl.schema.bo.wallet.IssueCouponBo;
import com.ddwl.schema.util.DateUtil;
import com.ddwl.schema.vo.base.PageVo;
import com.ddwl.schema.vo.base.RestVo;
import com.ddwl.schema.vo.funds.OrderPaymentVo;
import com.ddwl.schema.vo.order.OrderInfoVo;
import com.ddwl.schema.vo.order.OrderSpuVo;
import com.ddwl.schema.vo.shop.ShopVo;
import com.ddwl.schema.vo.user.UpgradeAgentOrderVo;
import com.ddwl.schema.vo.user.UpgradeAgentPayOrderVo;
import com.ddwl.schema.vo.user.UpgradeAgentVo;
import com.ddwl.schema.vo.user.UserVo;
import com.ddwl.user.dao.IdentityCardDao;
import com.ddwl.user.dao.UpgradeAgentOrderDao;
import com.ddwl.user.dao.UserDao;
import com.ddwl.user.dao.model.IdentityCard;
import com.ddwl.user.dao.model.User;
import com.ddwl.user.model.UpgradeAgentOrder;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Author hemiaojun
 * @Date 2021/9/23 18:19
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UpgradeAgentOrderService {

    private final UpgradeAgentOrderDao upgradeAgentOrderDao;
    private final UserDao userDao;
    private final IdentityCardDao identityCardDao;
    private final RabbitTemplate rabbitTemplate;
    private final FundsApi fundsApi;
    private final WalletApi walletApi;
    private final GateApi gateApi;
    private final ShopApi shopApi;

    public UpgradeAgentPayOrderVo ordering(AgentOrderBo bo) {
        User superior = userDao.selectByPrimaryKey(bo.getSuperiorId());
        ParamException.isNull(superior, "上级用户不存在");
        ParamException.isTrue((null == superior.getProfitLevel() || superior.getProfitLevel() <= UserEnum.ProfitLevelEnum.PERSONAL.getLevel()), "上级用户代理等级过低");

        if (UserEnum.ProfitLevelEnum.STORE.getLevel().equals(superior.getProfitLevel())) {
            ParamException.isFalse(UserEnum.ProfitLevelEnum.PERSONAL.getLevel().equals(bo.getProfitLevel()), "店铺代理下级只能是个人代理");
        }
        if (UserEnum.ProfitLevelEnum.ZONE.getLevel().equals(superior.getProfitLevel())) {
            ParamException.isFalse(UserEnum.ProfitLevelEnum.PERSONAL.getLevel().equals(bo.getProfitLevel()) || UserEnum.ProfitLevelEnum.STORE.getLevel().equals(bo.getProfitLevel()), "区域代理下级只能是店铺代理或者个人代理");
        }

        String agentName = GateEnum.DictionaryField.PERSONAL_AGENT_COST.name();
        if (UserEnum.ProfitLevelEnum.STORE.getLevel().equals(bo.getProfitLevel())) {
            agentName = GateEnum.DictionaryField.STORE_AGENT_COST.name();
        }

        UpgradeAgentPayOrderVo vo = new UpgradeAgentPayOrderVo();
        UpgradeAgentOrder exist = upgradeAgentOrderDao.queryExistOrder(bo.getUserId(), bo.getProfitLevel(), bo.getSuperiorId());
        if (null != exist) {
            ParamException.isTrue(OrderEnum.PayStatus.SUCCEED.getCode().equals(exist.getPayStatus()), "该订单已经支付成功！");
            if (OrderEnum.PayStatus.CRE.getCode().equals(exist.getPayStatus()) || OrderEnum.PayStatus.FILL.getCode().equals(exist.getPayStatus())) {
                createPayOrder(exist);
                vo.setOrderId(exist.getId());
                vo.setPrice(exist.getPayAmount());
                return vo;
            }
        }

        String result = gateApi.getSettingVal(GateEnum.DictionaryTag.TAG_SYSTEM.name(), agentName).getResult();
        UpgradeAgentOrder uao = BeanConverUtils.convertBean(bo, UpgradeAgentOrder.class);
        uao.setAgentType(bo.getProfitLevel());
        uao.setPayAmount(new BigDecimal(result));
        uao.setPayStatus(OrderEnum.PayStatus.CRE.getCode());
        uao.setStatus(BaseEnum.ApplyEnum.CRE.getCode());
        uao.setExpirationTime(DateUtil.getTimeAfterSomeMinute(30));
        uao.setSendStatus(BaseEnum.StatusEnum.DISABLE.getCode());
        upgradeAgentOrderDao.insert(uao);
        User entity = new User();
        entity.setId(bo.getUserId());
        entity.setImmediateSuperior(bo.getSuperiorId());
        entity.setImmediateSuperiorName(superior.getNickname());
        userDao.updateByPrimaryKeySelective(entity);
        createPayOrder(uao);
        vo.setOrderId(uao.getId());
        vo.setPrice(uao.getPayAmount());
        return vo;
    }

    private void createPayOrder(UpgradeAgentOrder order) {
        PayOrderCreBo payOrderCreBo = BeanConverUtils.convertBean(order, PayOrderCreBo.class);
        payOrderCreBo.setProduct(order.getPk());
        payOrderCreBo.setOrderId(order.getId());
        payOrderCreBo.setOrderType(OrderTypeEnum.JOIN_AGENT.getCode());
        payOrderCreBo.setTotalAmount(order.getPayAmount());
        payOrderCreBo.setExpirationTime(order.getExpirationTime());
        payOrderCreBo.setNotifyMethod(RabbitMqConstants.UPGRADE_AGENT_QUEUE);
        log.info("fundsApi.create param {}", JSON.toJSONString(payOrderCreBo));
        RestVo<OrderPaymentVo> orderPayVoRestVo = fundsApi.create(payOrderCreBo);
        log.info("fundsApi.create result {}", JSON.toJSONString(orderPayVoRestVo));
    }

    public void orderPayCallBack(OrderPaymentVo orderPaymentVo) {
        UpgradeAgentOrder upgradeAgentOrder = upgradeAgentOrderDao.selectByPrimaryKey(orderPaymentVo.getOrderId());
        ParamException.isNull(upgradeAgentOrder, "用户升级代理订单不存在");
        UpgradeAgentOrder entity = new UpgradeAgentOrder();
        entity.setId(upgradeAgentOrder.getId());
        entity.setPayStatus(orderPaymentVo.getTradeStatus());
        entity.setStatus(orderPaymentVo.getTradeStatus());
        entity.setPayType(orderPaymentVo.getPayType());
        upgradeAgentOrderDao.updateByPrimaryKeySelective(entity);

        User user = new User();
        user.setId(upgradeAgentOrder.getUserId());
        user.setProfitLevel(upgradeAgentOrder.getAgentType());
        userDao.updateByPrimaryKeySelective(user);

        if (UserEnum.ProfitLevelEnum.PERSONAL.getLevel().equals(upgradeAgentOrder.getAgentType())) {
            String result = gateApi.getSettingVal(GateEnum.DictionaryTag.TAG_SYSTEM.name(), GateEnum.DictionaryField.AGENT_COUPON_ID.name()).getResult();
            List<IssueCouponBo> list = new ArrayList();
            IssueCouponBo bo = new IssueCouponBo();
            bo.setUserId(upgradeAgentOrder.getUserId());
            bo.setCouponId(result);
            bo.setQty(4);
            list.add(bo);
            walletApi.issueCoupon(list);
            // 往公益账户里面赠送4双鞋的公益金
            walletApi.changeWallet(upgradeAgentOrder.getId(), UserEnum.AccountEnum.CHARITY_ACCOUNT.getId(), DistConstant.WalletFlowType.CHARITY_FUND.getType(),
                    BigDecimal.ONE.add(RandomUtil.randomBigDecimal()).multiply(new BigDecimal(4)).setScale(2, RoundingMode.HALF_UP));
        } else {
            // 往公益账户里面赠送8双鞋的公益金
            walletApi.changeWallet(upgradeAgentOrder.getId(), UserEnum.AccountEnum.CHARITY_ACCOUNT.getId(), DistConstant.WalletFlowType.CHARITY_FUND.getType(),
                    BigDecimal.ONE.add(RandomUtil.randomBigDecimal()).multiply(new BigDecimal(8)).setScale(2, RoundingMode.HALF_UP));
        }
        createDistOrder(orderPaymentVo, upgradeAgentOrder.getAgentType());
    }

    /**
     * 创建分销单
     */
    private void createDistOrder(OrderPaymentVo orderPayVo, Integer agentType) {
        String agentName = GateEnum.DictionaryField.PERSONAL_AGENT_PROFIT.name();
        if (UserEnum.ProfitLevelEnum.STORE.getLevel().equals(agentType)) {
            agentName = GateEnum.DictionaryField.STORE_AGENT_PROFIT.name();
        }
        String result = gateApi.getSettingVal(GateEnum.DictionaryTag.TAG_PROFIT.name(), agentName).getResult();

        //拼装佣金所需订单
        OrderInfoVo orderInfoVo = new OrderInfoVo();
        orderInfoVo.setAmount(orderPayVo.getAmount());
        orderInfoVo.setId(orderPayVo.getOrderId());
        orderInfoVo.setUserId(orderPayVo.getUserId());
        orderInfoVo.setPayAmount(orderPayVo.getAmount());
        orderInfoVo.setSource(orderPayVo.getUserId());
        orderInfoVo.setPayTime(orderPayVo.getGmtCreated());
        orderInfoVo.setConfirmTime(orderPayVo.getGmtCreated());
        orderInfoVo.setShopId(orderPayVo.getShopId());
        orderInfoVo.setStatus(OrderEnum.OrderStatus.RECEIVED.getCode());
        orderInfoVo.setPlatformTag(GoodsEnum.CategoryTypeEnum.PLATFORM.getCode());
        orderInfoVo.setDistType(DistConstant.DistrConfigType.AGENT.getCode());
        List<OrderSpuVo> orderSpus = new ArrayList<>();
        OrderSpuVo orderSpuVo = new OrderSpuVo();
        orderSpuVo.setRealPrice(orderPayVo.getAmount());
        orderSpuVo.setPrice(orderPayVo.getAmount());
        orderSpuVo.setProfitPrice(new BigDecimal(result));
        orderSpuVo.setItemName("代理费");
        orderSpuVo.setSkuQty(1);
        orderSpus.add(orderSpuVo);
        orderInfoVo.setSkuSnapshoot(JSON.toJSONString(orderSpus));

        String disOrder = JSON.toJSONString(orderInfoVo);
        rabbitTemplate.convertAndSend(RabbitMqConstants.DIST_ORDER_CALCULATE_QUEUE, disOrder);
    }

    public String payAgentCost(AgentPayOrderBo bo) {
        ParamException.isTrue(BaseEnum.ProductEnum.WBM.getName().equals(bo.getProduct()) && !StringUtils.hasText(bo.getOpenId()), "小程序支付openId不能为空");
        UpgradeAgentOrder order = upgradeAgentOrderDao.selectByPrimaryKey(bo.getOrderId());
        ParamException.isNull(order, "该订单不存在");
        FundsPaymentBo paymentBo = BeanConverUtils.convertBean(bo, FundsPaymentBo.class);
        log.info("fundsApi.payment param {}", JSON.toJSONString(paymentBo));
        RestVo<String> restVo = fundsApi.payment(paymentBo);
        log.info("fundsApi.payment result {}", JSON.toJSONString(restVo));
        return restVo.getResult();
    }

    public UpgradeAgentVo getSuperiorAgent(String keyWord, String userId) {
        User user = userDao.selectByPrimaryKey(userId);
        ParamException.isNull(user, "当前用户不存在");
        ParamException.isFalse(UserEnum.ProfitLevelEnum.NORMAL.getLevel().equals(user.getProfitLevel()), "您已经是代理用户");

        User superior = userDao.queryByKeyword(keyWord);
        ParamException.isNull(superior, "上级用户不存在");
        ParamException.isTrue((null == superior.getProfitLevel() || superior.getProfitLevel() <= UserEnum.ProfitLevelEnum.PERSONAL.getLevel()), "上级用户代理等级过低");

        UpgradeAgentVo vo = BeanConverUtils.convertBean(superior, UpgradeAgentVo.class);
        vo.setUserId(superior.getId());

        ShopVo shopVo = shopApi.getSimpleShopByUserId(userId).getResult();
        if (null != shopVo) {
            vo.setHasShopFlag(BaseEnum.StatusEnum.ENABLE.getCode());
        } else {
            vo.setHasShopFlag(BaseEnum.StatusEnum.DISABLE.getCode());
        }

        IdentityCard identityCard = identityCardDao.queryUserApply(userId);
        if (null != identityCard) {
            vo.setAuthFlag(BaseEnum.StatusEnum.ENABLE.getCode());
        } else {
            vo.setAuthFlag(BaseEnum.StatusEnum.DISABLE.getCode());
        }

        List<UpgradeAgentVo.UpgradeAgentConfig> list = new ArrayList<>();
        Map<String, String> resultMap = gateApi.getSettingByTag(GateEnum.DictionaryTag.TAG_UPGRADE_AGENT.name()).getResult();
        if (UserEnum.ProfitLevelEnum.STORE.getLevel().equals(superior.getProfitLevel())) {
            UpgradeAgentVo.UpgradeAgentConfig config = getUpgradeAgentConfig(UserEnum.ProfitLevelEnum.PERSONAL.getLevel()
                    , resultMap.get(GateEnum.DictionaryField.PERSONAL_AGENT_COST.name()), resultMap.get(GateEnum.DictionaryField.PERSONAL_AGENT_DESC.name()));
            list.add(config);
        }
        if (UserEnum.ProfitLevelEnum.ZONE.getLevel().equals(superior.getProfitLevel())) {
            Map<String, String> result = gateApi.getSettingByTag(GateEnum.DictionaryTag.TAG_UPGRADE_AGENT.name()).getResult();
            UpgradeAgentVo.UpgradeAgentConfig personal = getUpgradeAgentConfig(UserEnum.ProfitLevelEnum.PERSONAL.getLevel(), result.get(GateEnum.DictionaryField.PERSONAL_AGENT_COST.name()), resultMap.get(GateEnum.DictionaryField.PERSONAL_AGENT_DESC.name()));
            list.add(personal);
            UpgradeAgentVo.UpgradeAgentConfig store = getUpgradeAgentConfig(UserEnum.ProfitLevelEnum.STORE.getLevel(), result.get(GateEnum.DictionaryField.STORE_AGENT_COST.name()), resultMap.get(GateEnum.DictionaryField.STORE_AGENT_DESC.name()));
            list.add(store);
        }
        vo.setConfigList(list);
        return vo;

    }

    private UpgradeAgentVo.UpgradeAgentConfig getUpgradeAgentConfig(Integer profitLevel, String result, String desc) {
        UpgradeAgentVo.UpgradeAgentConfig config = new UpgradeAgentVo.UpgradeAgentConfig();
        config.setProfitLevel(profitLevel);
        config.setPrice(new BigDecimal(result));
        config.setDesc(desc);
        return config;
    }

    /**
     * 查询申请代码订单
     *
     * @param pageBo
     * @return
     */
    public PageVo<UpgradeAgentOrderVo> pageAgentOrder(PageBo<UpgradeAgentPageBo> pageBo) {
        PageHelper.startPage(pageBo.getPage(), pageBo.getPageSize(), MySqlUtil.orderBy(pageBo.getSort(), pageBo.isAsc()));
        PageInfo<UpgradeAgentOrder> info = new PageInfo(upgradeAgentOrderDao.findList(pageBo.getParam()));
        List<UpgradeAgentOrder> orders = info.getList();
        if (CollectionUtils.isEmpty(orders)) {
            return new PageVo<>(info.getTotal(), pageBo.getPage(), pageBo.getPageSize(), new ArrayList<>());
        }
        List<String> userIds = orders.stream().map(UpgradeAgentOrder::getUserId).collect(Collectors.toList());
        List<User> users = userDao.selectByPrimaryKeys(userIds);
        List<ShopVo> shops = shopApi.getSimpleShopByUserIds(userIds).getResult();
        Map<String, UserVo> userMap = users.stream().collect(Collectors.toMap(User::getId, user -> BeanConverUtils.convertBean(user, UserVo.class)));
        Map<String, ShopVo> shopMap = shops.stream().collect(Collectors.toMap(ShopVo::getUserId, Function.identity(), (k1, k2) -> k1));
        List<UpgradeAgentOrderVo> list = orders.stream().map(order -> {
            UpgradeAgentOrderVo vo = BeanConverUtils.convertBean(order, UpgradeAgentOrderVo.class);
            vo.setUser(userMap.get(vo.getUserId()));
            vo.setShop(shopMap.get(vo.getUserId()));
            return vo;
        }).collect(Collectors.toList());
        return new PageVo<>(info.getTotal(), pageBo.getPage(), pageBo.getPageSize(), list);
    }

    /**
     * 标记店代样品已发货
     *
     * @param bo
     */
    public void agentSend(AgentSendBo bo) {
        UpgradeAgentOrder uao = BeanConverUtils.convertBean(bo, UpgradeAgentOrder.class);
        uao.setSendStatus(BaseEnum.StatusEnum.ENABLE.getCode());
        upgradeAgentOrderDao.updateByPrimaryKeySelective(uao);
    }
}
